package dict

import (
	"go_redis_service/interface/IDict"
	"sync"
)

type SyncDict struct {
	m sync.Map
}

func NewSyncDict() *SyncDict {
	return &SyncDict{}
}

func (dict *SyncDict) Get(key string) (val interface{}, exists bool) {
	val, ok := dict.m.Load(key)
	return val, ok
}

func (dict *SyncDict) Len() int {
	length := 0
	dict.m.Range(func(key, value any) bool {
		length++
		return true
	})
	return length
}

func (dict *SyncDict) Put(key string, val interface{}) (result int) {
	_, exists := dict.m.Load(key)
	dict.m.Store(key, val)
	if exists {
		// 代表没新增 该key已存在 覆盖了
		return 0
	}
	return 1
}

// PutIfAbsent
// @Description: key 不存在则插入
// @receiver dict
// @param key
// @param val
// @return result
func (dict *SyncDict) PutIfAbsent(key string, val interface{}) (result int) {
	_, exists := dict.m.Load(key)
	if exists {
		return 0
	} else {
		dict.m.Store(key, val)
		return 1
	}
}

// PutIfExist
// @Description: key 存在则更新 不存在在不动
// @receiver dict
// @param key
// @param val
// @return result
func (dict *SyncDict) PutIfExist(key string, val interface{}) (result int) {
	_, exists := dict.m.Load(key)
	if exists {
		dict.m.Store(key, val)
		return 1
	} else {
		return 0
	}
}

func (dict *SyncDict) Remove(key string) (result int) {
	_, exists := dict.m.Load(key)
	if !exists {
		return 0
	} else {
		dict.m.Delete(key)
		return 1
	}
}

func (dict *SyncDict) ForEach(consumer IDict.Consumer) {
	dict.m.Range(func(key, value any) bool {
		consumer(key.(string), value)
		return true
	})
}

func (dict *SyncDict) Keys() []string {
	keyArr := make([]string, dict.Len())
	i := 0
	dict.m.Range(func(key, value any) bool {
		keyArr[i] = key.(string)
		i++
		return true
	})
	return keyArr
}

func (dict *SyncDict) RandomKeys(limit int) []string {
	keyArr := make([]string, limit)
	for i := 0; i < limit; i++ {
		dict.m.Range(func(key, value any) bool {
			keyArr[i] = key.(string)
			return false
		})
	}
	return keyArr
}

func (dict *SyncDict) RandomDistinctKeys(limit int) []string {
	keyArr := make([]string, limit)
	i := 0
	dict.m.Range(func(key, value any) bool {
		keyArr[i] = key.(string)
		i++
		if i == limit {
			return false
		} else {
			return true
		}
	})
	return keyArr
}

func (dict *SyncDict) Clear() {
	*dict = *NewSyncDict()
}
